home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Toolkit / Multimedia Toolkit.iso / pascal / heaps.pas < prev    next >
Pascal/Delphi Source File  |  1993-02-25  |  12KB  |  576 lines

  1. UNIT Heaps;
  2.  
  3. INTERFACE
  4.  
  5. USES Memory, Objects;
  6.  
  7.  
  8.  
  9.  
  10. TYPE
  11.   PFreeListRec = ^TFreeListRec;
  12.   TFreeListRec = ARRAY[1..2] OF LONGINT;
  13.  
  14.   PHeap = ^THeap;
  15.   THeap =
  16.     OBJECT(TObject)
  17.       HHeapOrg  : POINTER;
  18.       HHeapPtr  : POINTER;
  19.       HHeapEnd  : POINTER;
  20.       HFreeList : PFreeListRec;
  21.  
  22.       CONSTRUCTOR Init(Buffer: POINTER; Size: LONGINT);
  23.       CONSTRUCTOR EmptyInit;
  24.       DESTRUCTOR  Done; VIRTUAL;
  25.  
  26.       PROCEDURE HGetMem (VAR Buf: POINTER; Size: WORD); VIRTUAL;
  27.       PROCEDURE HFreeMem(VAR Buf: POINTER; Size: WORD); VIRTUAL;
  28.  
  29.       FUNCTION HMemAvail   : LONGINT; VIRTUAL;
  30.       FUNCTION HMaxAvail   : LONGINT; VIRTUAL;
  31.       FUNCTION HTotalAvail : LONGINT; VIRTUAL;
  32.  
  33.       PROCEDURE TransferToSystem;   VIRTUAL;
  34.       PROCEDURE TransferFromSystem; VIRTUAL;
  35.       PROCEDURE BeginOperation;     VIRTUAL;
  36.       PROCEDURE EndOperation;       VIRTUAL;
  37.  
  38.       FUNCTION InHeap(P: POINTER) : BOOLEAN; VIRTUAL;
  39.  
  40.       FUNCTION  HNewStr         (S: STRING) : PString; VIRTUAL;
  41.       PROCEDURE HDisposeStr (VAR S: PString);          VIRTUAL;
  42.     END;
  43.  
  44.   PUmbHeap = ^TUmbHeap;
  45.   TUmbHeap =
  46.     OBJECT(THeap)
  47.       CONSTRUCTOR Init;
  48.       DESTRUCTOR  Done; VIRTUAL;
  49.     END;
  50.  
  51.   PHeapColl = ^THeapColl;
  52.   THeapColl =
  53.     OBJECT(THeap)
  54.       HeapColl : TCollection;
  55.  
  56.       CONSTRUCTOR Init;
  57.       DESTRUCTOR  Done;              VIRTUAL;
  58.  
  59.       PROCEDURE AddHeap   (H: PHeap); VIRTUAL;
  60.       PROCEDURE RemoveHeap(H: PHeap); VIRTUAL;
  61.  
  62.       PROCEDURE HGetMem (VAR Buf: POINTER; Size: WORD); VIRTUAL;
  63.       PROCEDURE HFreeMem(VAR Buf: POINTER; Size: WORD); VIRTUAL;
  64.  
  65.       FUNCTION HMemAvail   : LONGINT; VIRTUAL;
  66.       FUNCTION HMaxAvail   : LONGINT; VIRTUAL;
  67.       FUNCTION HTotalAvail : LONGINT; VIRTUAL;
  68.  
  69.       PROCEDURE TransferToSystem;   VIRTUAL;
  70.       PROCEDURE TransferFromSystem; VIRTUAL;
  71.       PROCEDURE BeginOperation;     VIRTUAL;
  72.       PROCEDURE EndOperation;       VIRTUAL;
  73.  
  74.       FUNCTION InHeap(P: POINTER) : BOOLEAN; VIRTUAL;
  75.     END;
  76.  
  77.  
  78.  
  79.  
  80. VAR
  81.   InitialHeapEnd : POINTER;
  82.   Heap           : THeap;
  83.   UmbHeap        : THeapColl;
  84.   FullHeap       : THeapColl;
  85.   TempHeap       : THeap;
  86.  
  87.  
  88.  
  89.  
  90. PROCEDURE InitHeapVariables;
  91. PROCEDURE DoneHeapVariables;
  92.  
  93. PROCEDURE InitUmbHeap;
  94. PROCEDURE ChangeSystemHeap (Size: LONGINT);
  95. PROCEDURE ShrinkSystemHeap (Size: LONGINT);
  96. PROCEDURE InitTempHeap     (Size: LONGINT);
  97. PROCEDURE DoneTempHeap;
  98.  
  99.  
  100.  
  101.  
  102. IMPLEMENTATION
  103.  
  104. USES UMBUnit, HexConversions;
  105.  
  106.  
  107.  
  108.  
  109. {----------------------------------------------------------------------------}
  110. { Functions that handle pointers.                                            }
  111. {____________________________________________________________________________}
  112.  
  113. FUNCTION IncPtr(P: POINTER; L: LONGINT) : POINTER;
  114.   BEGIN
  115.     IncPtr := Ptr(SEG(P^) + ((OFS(P^) + L) SHR 4), (OFS(P^) + L) AND 15);
  116.   END;
  117.  
  118.  
  119. FUNCTION NormalizePtr(P: POINTER) : POINTER;
  120.   BEGIN
  121.     NormalizePtr := Ptr(SEG(P^) + (OFS(P^) SHR 4), OFS(P^) AND 15);
  122.   END;
  123.  
  124.  
  125. FUNCTION LinealPtr(P: POINTER) : LONGINT;
  126.   BEGIN
  127.     LinealPtr := (LONGINT(SEG(P^)) SHL 4) + OFS(P^);
  128.   END;
  129.  
  130.  
  131.  
  132.  
  133. {----------------------------------------------------------------------------}
  134. { Utilities for initialising and managing heaps.                             }
  135. {____________________________________________________________________________}
  136.  
  137. PROCEDURE InitUmbHeap;
  138.   VAR
  139.     UMB : PUmbHeap;
  140.   BEGIN
  141.     REPEAT
  142.       New(UMB, Init);
  143.       IF UMB^.HTotalAvail <> 0 THEN
  144.         UmbHeap.AddHeap(UMB)
  145.       ELSE
  146.         BEGIN
  147.           Dispose(UMB, Done);
  148.           UMB := NIL;
  149.         END;
  150.     UNTIL UMB = NIL;
  151.   END;
  152.  
  153.  
  154. PROCEDURE ChangeSystemHeap(Size: LONGINT);
  155.   BEGIN
  156.     IF Size < LinealPtr(HeapPtr) - LinealPtr(HeapOrg) THEN
  157.       Size := LinealPtr(HeapPtr) - LinealPtr(HeapOrg)
  158.     ELSE IF Size > LinealPtr(InitialHeapEnd) - LinealPtr(HeapOrg) THEN
  159.       Size := LinealPtr(InitialHeapEnd) - LinealPtr(HeapOrg);
  160.  
  161.     HeapEnd := IncPtr(HeapOrg, Size);
  162.     Heap.TransferFromSystem;
  163.   END;
  164.  
  165.  
  166. PROCEDURE ShrinkSystemHeap(Size: LONGINT);
  167.   BEGIN
  168.     ChangeSystemHeap(Size);
  169.     SetMemTop(HeapEnd);
  170.   END;
  171.  
  172.  
  173. PROCEDURE InitTempHeap(Size: LONGINT);
  174.   VAR
  175.     SystemTot : LONGINT;
  176.   BEGIN
  177.     TempHeap.Done;
  178.  
  179.     SystemTot := Heap.HTotalAvail;
  180.     ChangeSystemHeap(SystemTot - Size);
  181.     Size := SystemTot - Heap.HTotalAvail;
  182.  
  183.     TempHeap.Init(Heap.HHeapEnd, Size);
  184.   END;
  185.  
  186.  
  187. PROCEDURE DoneTempHeap;
  188.   VAR
  189.     Size : LONGINT;
  190.   BEGIN
  191.     TempHeap.Done;
  192.  
  193.     Size := TempHeap.HTotalAvail;
  194.     ChangeSystemHeap(Heap.HTotalAvail+Size);
  195.  
  196.     TempHeap.EmptyInit;
  197.   END;
  198.  
  199.  
  200.  
  201.  
  202. {----------------------------------------------------------------------------}
  203. { THeap object implementation.                                               }
  204. {____________________________________________________________________________}
  205.  
  206. CONSTRUCTOR THeap.Init(Buffer: POINTER; Size: LONGINT);
  207.   BEGIN
  208.     TObject.Init;
  209.     IF Size > 0 THEN
  210.       BEGIN
  211.         HHeapEnd  := IncPtr(Buffer, Size);
  212.         HHeapEnd  := Ptr(SEG(HHeapEnd^), 0);
  213.  
  214.         Buffer   := NormalizePtr(Buffer);
  215.         IF OFS(Buffer^) <> 0 THEN
  216.           Buffer := Ptr(SEG(Buffer^) + 1, 0);
  217.         HHeapOrg  := Buffer;
  218.         HHeapPtr  := Buffer;
  219.         HFreeList := Buffer;
  220.         FillChar(HFreeList^, SizeOf(HFreeList^), 0);
  221.       END;
  222.   END;
  223.  
  224.  
  225. CONSTRUCTOR THeap.EmptyInit;
  226.   BEGIN
  227.     TObject.Init;
  228.   END;
  229.  
  230.  
  231. DESTRUCTOR  THeap.Done; 
  232.   BEGIN
  233.     HHeapOrg  := NIL;
  234.     HHeapPtr  := NIL;
  235.     HHeapEnd  := NIL;
  236.     HFreeList := NIL;
  237.     TObject.Done;
  238.   END;
  239.  
  240.  
  241. PROCEDURE THeap.HGetMem (VAR Buf: POINTER; Size: WORD); 
  242.   BEGIN
  243.     BeginOperation;
  244.     IF MaxAvail < Size THEN
  245.       Buf := NIL
  246.     ELSE
  247.       GetMem(Buf, Size);
  248.     EndOperation;
  249.   END;
  250.  
  251.  
  252. PROCEDURE THeap.HFreeMem(VAR Buf: POINTER; Size: WORD); 
  253.   BEGIN
  254.     IF Buf = NIL THEN EXIT;
  255.     IF NOT InHeap(Buf) THEN
  256.       BEGIN
  257.         WriteLn('Bad FreeMem: ', HexPtr(Buf));
  258.         EXIT;
  259.       END;
  260.     BeginOperation;
  261.     FreeMem(Buf, Size);
  262.     Buf := NIL;
  263.     EndOperation;
  264.   END;
  265.  
  266.  
  267. FUNCTION THeap.HMemAvail : LONGINT; 
  268.   BEGIN
  269.     BeginOperation;
  270.     HMemAvail := MemAvail;
  271.     EndOperation;
  272.   END;
  273.  
  274.  
  275. FUNCTION THeap.HMaxAvail : LONGINT; 
  276.   BEGIN
  277.     BeginOperation;
  278.     HMaxAvail := MaxAvail;
  279.     EndOperation;
  280.   END;
  281.  
  282.  
  283. FUNCTION THeap.HTotalAvail : LONGINT;
  284.   BEGIN
  285.     BeginOperation;
  286.     HTotalAvail := LinealPtr(HHeapEnd) - LinealPtr(HHeapOrg);
  287.     EndOperation;
  288.   END;
  289.  
  290.  
  291. PROCEDURE THeap.TransferToSystem;
  292.   BEGIN
  293.     HeapOrg  := HHeapOrg;
  294.     HeapPtr  := HHeapPtr;
  295.     HeapEnd  := HHeapEnd;
  296.     FreeList := HFreeList;
  297.   END;
  298.  
  299.  
  300. PROCEDURE THeap.TransferFromSystem;
  301.   BEGIN
  302.     HHeapOrg  := HeapOrg;
  303.     HHeapPtr  := HeapPtr;
  304.     HHeapEnd  := HeapEnd;
  305.     HFreeList := FreeList;
  306.   END;
  307.  
  308.  
  309. PROCEDURE THeap.BeginOperation;
  310.   BEGIN
  311.     IF @Self <> @Heap THEN
  312.       BEGIN
  313.         Heap.TransferFromSystem;
  314.         TransferToSystem;
  315.       END;
  316.   END;
  317.  
  318.  
  319. PROCEDURE THeap.EndOperation;
  320.   BEGIN
  321.     IF @Self <> @Heap THEN
  322.       BEGIN
  323.         TransferFromSystem;
  324.         Heap.TransferToSystem;
  325.       END
  326.     ELSE
  327.       BEGIN
  328.         TransferFromSystem;
  329.       END;
  330.   END;
  331.  
  332.  
  333. FUNCTION THeap.InHeap(P: POINTER) : BOOLEAN;
  334.   BEGIN
  335.     InHeap := (LinealPtr(P) >= LinealPtr(HHeapOrg)) AND
  336.               (LinealPtr(P) <  LinealPtr(HHeapPtr));
  337.   END;
  338.  
  339.  
  340. FUNCTION THeap.HNewStr(S: STRING) : PString;
  341.   VAR
  342.     NS : PString;
  343.   BEGIN
  344.     HGetMem(POINTER(NS), Length(S) + 1);
  345.     IF NS <> NIL THEN
  346.       NS^ := S;
  347.     HNewStr := NS;
  348.   END;
  349.  
  350.  
  351. PROCEDURE THeap.HDisposeStr(VAR S: PString);
  352.   BEGIN
  353.     HFreeMem(POINTER(S), Length(S^) + 1);
  354.   END;
  355.  
  356.  
  357.  
  358.  
  359. {----------------------------------------------------------------------------}
  360. { TUmbHeap object implementation.                                            }
  361. {____________________________________________________________________________}
  362.  
  363. CONSTRUCTOR TUmbHeap.Init;
  364.   VAR
  365.     L   : LONGINT;
  366.     Buf : POINTER;
  367.   BEGIN
  368.     L := UMBAllocate(Buf, 1000000);
  369.     IF Buf <> NIL THEN
  370.       THeap.Init(Buf, L)
  371.     ELSE
  372.       EmptyInit;
  373.   END;
  374.  
  375.  
  376. DESTRUCTOR TUmbHeap.Done;
  377.   BEGIN
  378.     IF HHeapOrg <> NIL THEN
  379.       UMBFree(HHeapOrg);
  380.   END;
  381.  
  382.  
  383.  
  384.  
  385. {----------------------------------------------------------------------------}
  386. { THeapColl object implementation.                                           }
  387. {____________________________________________________________________________}
  388.  
  389. CONSTRUCTOR THeapColl.Init;
  390.   BEGIN
  391.     EmptyInit;
  392.     HeapColl.Init(3, 2);
  393.   END;
  394.  
  395.  
  396. DESTRUCTOR THeapColl.Done;
  397.  
  398.   PROCEDURE DoFree(H: PHeap); FAR;
  399.     BEGIN
  400.       HeapColl.Delete(H);
  401.       IF SEG(H^) <> SEG(Heap) THEN
  402.         Dispose(H, Done);
  403.     END;
  404.   
  405.   BEGIN
  406.     HeapColl.ForEach(@DoFree);
  407.   END;
  408.  
  409.  
  410. PROCEDURE THeapColl.AddHeap(H: PHeap);
  411.   BEGIN
  412.     HeapColl.Insert(H);
  413.   END;
  414.  
  415.  
  416. PROCEDURE THeapColl.RemoveHeap(H: PHeap);
  417.   BEGIN
  418.     HeapColl.Delete(H);
  419.   END;
  420.  
  421.  
  422. PROCEDURE THeapColl.HGetMem (VAR Buf: POINTER; Size: WORD);
  423.  
  424.   FUNCTION Get(VAR H: THeap) : BOOLEAN; FAR;
  425.     BEGIN
  426.       H.HGetMem(Buf, Size);
  427.       Get := Buf <> NIL;
  428.     END;
  429.  
  430.   BEGIN { HGetMem }
  431.     Buf := NIL;
  432.     HeapColl.FirstThat(@Get);
  433.   END;
  434.  
  435.  
  436. PROCEDURE THeapColl.HFreeMem(VAR Buf: POINTER; Size: WORD);
  437.  
  438.   FUNCTION DoFree(VAR H: THeap) : BOOLEAN; FAR;
  439.     BEGIN
  440.       IF H.InHeap(Buf) THEN
  441.         BEGIN
  442.           DoFree := TRUE;
  443.           H.HFreeMem(Buf, Size);
  444.         END
  445.       ELSE
  446.         DoFree := FALSE;
  447.     END;
  448.  
  449.   BEGIN { HFreeMem }
  450.     IF Buf = NIL THEN EXIT;
  451.     HeapColl.FirstThat(@DoFree);
  452.     Buf := NIL;
  453.   END;
  454.  
  455.  
  456. FUNCTION THeapColl.HMemAvail : LONGINT; 
  457.   VAR
  458.     Sum : LONGINT;
  459.  
  460.   PROCEDURE Add(VAR H: THeap); FAR;
  461.     BEGIN
  462.       INC(Sum, H.HMemAvail);
  463.     END;
  464.  
  465.   BEGIN { HMemAvail }
  466.     Sum := 0;
  467.     HeapColl.ForEach(@Add);
  468.     HMemAvail := Sum;
  469.   END;
  470.  
  471.  
  472. FUNCTION THeapColl.HMaxAvail : LONGINT; 
  473.   VAR
  474.     Sum : LONGINT;
  475.  
  476.   PROCEDURE FindMax(VAR H: THeap); FAR;
  477.     VAR
  478.       Max : LONGINT;
  479.     BEGIN
  480.       Max := H.HMaxAvail;
  481.       IF Max > Sum THEN
  482.         Sum := Max;
  483.     END;
  484.  
  485.   BEGIN { HMaxAvail }
  486.     Sum := 0;
  487.     HeapColl.ForEach(@FindMax);
  488.     HMaxAvail := Sum;
  489.   END;
  490.  
  491.  
  492. FUNCTION THeapColl.HTotalAvail : LONGINT;
  493.   VAR
  494.     Sum : LONGINT;
  495.  
  496.   PROCEDURE Add(VAR H: THeap); FAR;
  497.     BEGIN
  498.       INC(Sum, H.HTotalAvail);
  499.     END;
  500.  
  501.   BEGIN { HTotalAvail }
  502.     Sum := 0;
  503.     HeapColl.ForEach(@Add);
  504.     HTotalAvail := Sum;
  505.   END;
  506.  
  507.  
  508. PROCEDURE THeapColl.TransferToSystem;
  509.   BEGIN
  510.   END;
  511.  
  512.  
  513. PROCEDURE THeapColl.TransferFromSystem; 
  514.   BEGIN
  515.   END;
  516.  
  517.  
  518. PROCEDURE THeapColl.BeginOperation;
  519.   BEGIN
  520.   END;
  521.  
  522.  
  523. PROCEDURE THeapColl.EndOperation;
  524.   BEGIN
  525.   END;
  526.  
  527.  
  528. FUNCTION THeapColl.InHeap(P: POINTER) : BOOLEAN;
  529.  
  530.   FUNCTION IsIn(VAR H: THeap) : BOOLEAN; FAR;
  531.     BEGIN
  532.       IsIn := H.InHeap(P);
  533.     END;
  534.  
  535.   BEGIN { InHeap }
  536.     InHeap := TRUE;
  537.     InHeap := HeapColl.FirstThat(@IsIn) <> NIL;
  538.   END;
  539.  
  540.  
  541.  
  542.  
  543. {----------------------------------------------------------------------------}
  544. { Normal Heap variables initialisation and deinitialisation. Looking for     }
  545. { every tiny bit of memory available.                                        }
  546. {____________________________________________________________________________}
  547.  
  548. PROCEDURE InitHeapVariables;
  549.   BEGIN
  550.     UmbHeap.Init;
  551.     FullHeap.AddHeap(@UmbHeap);
  552.     FullHeap.AddHeap(@Heap);
  553.  
  554.   END;
  555.  
  556.  
  557. PROCEDURE DoneHeapVariables;
  558.   BEGIN
  559.     FullHeap.RemoveHeap(@Heap);
  560.     FullHeap.Done;
  561.     TempHeap.Done;
  562.   END;
  563.  
  564.  
  565. BEGIN
  566.   InitialHeapEnd := HeapEnd;
  567.  
  568.   Heap.EmptyInit;
  569.   Heap.HHeapOrg  := HeapOrg;
  570.   Heap.HHeapPtr  := HeapPtr;
  571.   Heap.HHeapEnd  := HeapEnd;
  572.   Heap.HFreeList := FreeList;
  573.  
  574.   FullHeap.Init;
  575.   TempHeap.EmptyInit;
  576. END.